package com.lfy.modules.blog.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.lfy.modules.blog.cache.AuthCache;
import com.lfy.modules.blog.domain.RoleAuthorityContactEntity;
import com.lfy.modules.blog.domain.RoleEntity;
import com.lfy.modules.blog.domain.RoleRouteContactEntity;
import com.lfy.modules.blog.service.*;
import com.lfy.modules.common.domain.entity.UserEntity;
import com.lfy.modules.blog.domain.dto.role.AuthDTO;
import com.lfy.modules.blog.domain.vo.auth.AuthAllVO;
import com.lfy.modules.blog.domain.vo.role.SaveRouteByRoleDTO;
import com.lfy.modules.common.anno.Authentication;
import com.lfy.modules.common.anno.AutoUser;
import com.lfy.modules.common.anno.CheckRole;
import com.lfy.modules.blog.domain.converter.RoleConverter;
import com.lfy.modules.blog.domain.dto.role.RoleDTO;
import com.lfy.modules.blog.domain.group.RemoveGroup;
import com.lfy.modules.blog.domain.group.SaveGroup;
import com.lfy.modules.blog.domain.group.UpdateGroup;
import com.lfy.modules.blog.domain.vo.role.RoleVO;
import com.lfy.modules.blog.domain.vo.role.RouteTreeVO;
import com.lfy.modules.common.custom.constants.AuthConstant;
import com.lfy.modules.common.domain.BaseEnum;
import com.lfy.modules.common.domain.PageResultVO;
import com.lfy.modules.common.domain.R;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;
import java.util.Set;

import static com.lfy.modules.common.custom.constants.PageConstant.MAX_PAGE_SIZE;

/**
 *  权限相关接口
 *
 * @author <a href="https://www.lvfeiy.top">lvfeiyang</a>
 * @date 2024/4/25 1:01
 */
@RestController
@RequestMapping("/admin")
public class RoleManagementController implements RoleConverter {
    @Resource
    private RoleService service;
    @Resource
    private RouteService routeService;
    @Resource
    private AuthorityService authorityService;
    @Resource
    private RoleAuthorityContactService roleAuthorityContactService;
    @Resource
    private RoleRouteContactService routeContactService;

    /**
     * 获取角色列表
     * @param pageSize 每页大小
     * @param pageNum 页码
     * @param name 角色名称 可选
     * @return R
     */
    @GetMapping("/get/roleList")
    @Authentication("sys:role:get")
    public R<PageResultVO<RoleVO>> getRoleList(@RequestParam("pageSize") Integer pageSize,
                                               @RequestParam("pageNum") Integer pageNum,String name){
        if(pageSize>MAX_PAGE_SIZE){
            return R.error(BaseEnum.commonEnum.ERROR_PAGE_SIZE);
        }
        return service.getRoleList(pageSize,pageNum,name);
    }

    /**
     * 添加角色
     * @param saveRoleDTO 角色信息
     * @return R
     */
    @PostMapping("/add/role")
    @Authentication("sys:role:update")
    @CheckRole(level = "#saveRoleDTO.roleLev")
    public R<Void> addRole(@Validated(SaveGroup.class) @RequestBody RoleDTO saveRoleDTO,@AutoUser UserEntity user ){
        RoleEntity roleEntity = this.roleDTOToRoleEntity(saveRoleDTO);
        roleEntity.setCreateBy(user.getId());
        service.save(roleEntity);
        AuthCache.addRole(roleEntity.getId());
        return R.success();
    }

    /**
     * 更新角色
     * @param updateRoleDTO 角色信息
     * @return R
     */
    @PostMapping("/update/role")
    @Authentication("sys:role:update")
    @CheckRole(level = "#updateRoleDTO.roleLev",roleId = "#updateRoleDTO.id")
    public R<Void> updateRole(@Validated(UpdateGroup.class) @RequestBody RoleDTO updateRoleDTO){
        String roleKey = updateRoleDTO.getRoleKey();
        if(Objects.nonNull(roleKey)){
            if(AuthConstant.ROOT_ROLE.equals(roleKey)){
                return R.error(BaseEnum.authEnum.NO_AUTH);
            }
        }
        service.updateById(this.roleDTOToRoleEntity(updateRoleDTO));
        return R.success();
    }

    /**
     * 删除角色
     * @param removeRoleDTO 角色id
     * @return R
     */
    @PostMapping("/remove/role")
    @Authentication("sys:role:remove")
    @CheckRole(roleId = "#removeRoleDTO.id")
    @Transactional
    public R<Void> removeRole(@Validated(RemoveGroup.class)@RequestBody RoleDTO removeRoleDTO){

        service.removeById(removeRoleDTO.getId());
        routeContactService.remove(new LambdaQueryWrapper<RoleRouteContactEntity>().in(RoleRouteContactEntity::getRoleId,removeRoleDTO.getId()));
        roleAuthorityContactService.remove(new LambdaQueryWrapper<RoleAuthorityContactEntity>().in(RoleAuthorityContactEntity::getRoleId,removeRoleDTO.getId()));
        AuthCache.removeRole(removeRoleDTO.getId());
        return R.success();
    }

    /**
     * 获取全部路由字典
     */
    @GetMapping("/get/routes")
    @Authentication("sys:route:get")
    public R<List<RouteTreeVO>> getRouteList(){
        return routeService.getRouteTree();
    }

    /**
     * 获取角色已有的路由树
     * @param id role_id
     * @return R
     */
    @GetMapping("/get/routeTree/{id}")
    public R<List<RouteTreeVO>> getRouteTreeListByRoleId(@PathVariable("id") Long id ){
        return routeService.getRouteTreeListByRoleId(id);
    }
    /**
     * 获取角色已有的路由id
     */
    @GetMapping("/get/route/{id}")
    public R<Set<Long>> getRouteIdByRoleId(@PathVariable("id") Long id ){
        return routeService.getRouteIdByRoleId(id);
    }

    /**
     * 给角色分配路由
     */
    @PostMapping("/add/routeByroleId")
    @Authentication("sys:route:update")
    @CheckRole(roleId = "#dto.roleId")
    public R<Void> addRouteByRoleId(@Validated @RequestBody SaveRouteByRoleDTO dto,@AutoUser UserEntity user){

        return routeService.addRouteByRoleId(dto);
    }
    /**
     * 根据角色删除路由
     */
    @PostMapping("/remove/routeByroleId")
    @Authentication("sys:route:update")
    @CheckRole(roleId = "#dto.roleId")
    public R<Void> removeRouteByRoleId(@Validated @RequestBody SaveRouteByRoleDTO dto,@AutoUser UserEntity user){
        Long role = user.getRole();
        RoleEntity entity = this.service.getById(role);
        RoleEntity removeEntity = this.service.getById(dto.getRoleId());
        if(entity.getRoleLev() > removeEntity.getRoleLev()){
            return R.error(BaseEnum.authEnum.NO_AUTH);
        }
        return this.routeService.removeRouteByRoleId(dto);
    }
    /**
     * 获取全部权限信息
     */
    @GetMapping("/get/allAuth")
    public R<List<AuthAllVO>> getAllRole(){
        return R.success(authorityService.getAuthAll());
    }
    /**
     * 获取角色已有的权限id
     */
    @Authentication("sys:auth:get")
    @GetMapping("/get/auth/{id}")
    public R<Set<Long>> getAuthIdByRoleId(@PathVariable("id") Long id ){
        return authorityService.getAuthIdByRoleId(id);
    }
    /**
     * 给角色分配权限
     */
    @PostMapping("/add/authByroleId")
    @Authentication("sys:auth:update")
    @CheckRole(roleId = "#dto.roleId")
    public R<Void> addAuthByRoleId(@Validated @RequestBody AuthDTO dto){

        return authorityService.addAuthByRoleId(dto);
    }
    /**
     * 根据角色删除权限
     */
    @PostMapping("/remove/authByroleId")
    @Authentication("sys:auth:update")
    @CheckRole(roleId = "#dto.roleId")
    public R<Void> removeAuthByRoleId(@Validated @RequestBody AuthDTO dto){

        return this.authorityService.removeAuthByRoleId(dto);
    }

}
